/**
 * @file mobjbuf.h
 *
 * @author yhuan416<yhuan416@foxmail.com>
 * @date 2025-8-14
 *
 * @brief 携带淘汰机制的内存池
 *          申请新空间时, 通过外部回调淘汰部分旧数据
 *
 * @date 2025-8-14
 *          初次提交
 */
#ifndef __mobjbuf_h__
#define __mobjbuf_h__

#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>

#define MOBJBUF_ALIGN (8) // 对齐字节数

#ifdef __cplusplus__
extern "C" {
#endif

typedef enum mobjbuf_evict_status
{
    MOBJBUF_EVICT_NONE = 0,
    MOBJBUF_EVICT_DONE = 1,
} mobjbuf_evict_status_t;

// 头部结构体：存储块元数据（双向链表节点）
typedef struct mobjbuf_header
{
    struct mobjbuf_header *prev;
    struct mobjbuf_header *next;
    size_t size;           // 块总大小（包括头部）
    unsigned char is_free; // 空闲标志
    char padding[7];       // 保留字段, 用于对齐
    char data[0];
} mobjbuf_header_t;

#define mobjbuf_header_format_s "%p{prev: <%p>, next: <%p>, size: [%zu], is_free: [%d], data: [%p]}"
#define mobjbuf_header_format(_header)      \
    (_header),                              \
        (_header)->prev, \
        (_header)->next, \
        (_header)->size,    \
        (_header)->is_free, \
        (_header)->data

typedef struct mobjbuf_list
{
    struct mobjbuf_header *list;
    size_t count;
    size_t bytes;
} mobjbuf_list_t;

#define mobjbuf_list_format_s "%p{list: [%p], count: [%zu], bytes: [%zu]}"
#define mobjbuf_list_format(_list)      \
    (_list),                            \
        (_list) ? (_list)->list : NULL, \
        (_list) ? (_list)->count : 0,   \
        (_list) ? (_list)->bytes : 0

// 内存池管理器
typedef struct
{
    void *buffer;              // 外部传入的缓冲区
    size_t buf_size;           // 缓冲区总大小
    mobjbuf_list_t alloc_list; // 已分配链表
    mobjbuf_list_t free_list;  // 空闲链表
    size_t min_block_size;     // 最小块大小（头部+最小数据）
} mobjbuf_t;

#define mobjbuf_format_s "%p{buffer: [%p], buf_size: [%zu], alloc_list: " mobjbuf_list_format_s ", free_list: " mobjbuf_list_format_s ", min_block_size: [%zu]}"
#define mobjbuf_format(_objbuf)                                           \
    (_objbuf),                                                            \
        (_objbuf)->buffer,                             \
        (_objbuf)->buf_size,                              \
        mobjbuf_list_format(&((_objbuf)->alloc_list)), \
        mobjbuf_list_format(&((_objbuf)->alloc_list)),  \
        (_objbuf)->min_block_size

/**
 * @brief 回收回调函数类型
 *
 * @param objbuf 内存池对象
 * @param userdata 用户数据指针
 * @param require_size 需要释放的内存大小
 *
 * @return see @{enum mobjbuf_evict_status}
 *          MOBJBUF_EVICT_DONE: 完成数据释放
 *          MOBJBUF_EVICT_NONE: 没有数据可以释放
 */
typedef int (*mobjbuf_discard_callback_fn)(mobjbuf_t *objbuf, size_t require_size, void *userdata);

/**
 * @brief 初始化内存池
 *
 * @param objbuf 内存池对象
 * @param buffer 外部传入的缓冲区
 * @param buf_size 缓冲区大小
 *
 * @return 0: 成功, -1: 失败
 */
extern int mobjbuf_init(mobjbuf_t *objbuf, void *buffer, size_t buf_size);

/**
 * @brief 分配内存
 *
 * @param objbuf 内存池对象
 * @param size 需要的大小
 * @param evict_callback 逐出回调函数
 * @param userdata 用户数据指针
 *
 * @return 分配的内存指针，失败则返回NULL
 */
extern void *mobjbuf_alloc(mobjbuf_t *objbuf, size_t size, mobjbuf_discard_callback_fn discard_callback, void *userdata);

/**
 * @brief 释放内存
 *
 * @param objbuf 内存池对象
 * @param ptr 要释放的内存指针
 */
extern void mobjbuf_free(mobjbuf_t *objbuf, void *ptr);

/**
 * @brief 释放内存（不合并空闲块, 可以在释放多个块后调用一次合并, 避免反复遍历）
 *
 * @param objbuf 内存池对象
 * @param ptr 要释放的内存指针
 */
extern void mobjbuf_free_without_merge(mobjbuf_t *objbuf, void *ptr);

/**
 * @brief 合并所有空闲块
 *
 * @param objbuf 内存池对象
 */
extern void mobjbuf_merge_free_blocks(mobjbuf_t *objbuf);

/**
 * @brief 打印mobjbuf信息
 */
extern void mobjbuf_dump(mobjbuf_t *objbuf);

#ifdef __cplusplus__
}
#endif
#endif /* __mobjbuf_h__ */
